package club.itstudio.IContainer.controller.teacher;

import club.itstudio.IContainer.annotation.LoginRequired;
import club.itstudio.IContainer.annotation.TeacherRequired;
import club.itstudio.IContainer.entity.Course;
import club.itstudio.IContainer.entity.StudentCourse;
import club.itstudio.IContainer.entity.StudentCourseApplication;
import club.itstudio.IContainer.entity.User;
import club.itstudio.IContainer.exception.ParamInvalidException;
import club.itstudio.IContainer.exception.PermissionException;
import club.itstudio.IContainer.service.AuthService;
import club.itstudio.IContainer.service.CourseService;
import club.itstudio.IContainer.service.StudentCourseApplicationService;
import club.itstudio.IContainer.service.StudentCourseService;
import club.itstudio.IContainer.util.Result;
import club.itstudio.IContainer.util.ResultUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.RowMapper;
import org.springframework.web.bind.annotation.*;

import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@RestController
@RequestMapping("/teacher/course")
public class TeacherCourseController {

    private CourseService courseService;
    private AuthService authService;
    private JdbcTemplate jdbcTemplate;
    private StudentCourseApplicationService studentCourseApplicationService;
    private StudentCourseService studentCourseService;

    @Autowired
    public void setStudentCourseService(StudentCourseService studentCourseService) {
        this.studentCourseService = studentCourseService;
    }

    @Autowired
    public void setStudentCourseApplicationService(StudentCourseApplicationService studentCourseApplicationService) {
        this.studentCourseApplicationService = studentCourseApplicationService;
    }

    @Autowired
    public void setJdbcTemplate(JdbcTemplate jdbcTemplate) {
        this.jdbcTemplate = jdbcTemplate;
    }

    @Autowired
    public void setCourseService(CourseService courseService) {
        this.courseService = courseService;
    }

    @Autowired
    public void setAuthService(AuthService authService) {
        this.authService = authService;
    }

    @GetMapping
    @LoginRequired
    @TeacherRequired
    public Result getTeacherCourses(@RequestParam int page, @RequestParam int limit) {
        User user = authService.threadLocalUsers.get();
        Map<String, Object> result = new HashMap<>();
        result.put("total", courseService.getCourseNumByTeacherID(user.id));
        result.put("content", courseService.getCourseListByTeacherID(page, limit, user.id));
        return ResultUtil.success(result);
    }

    @PostMapping
    @LoginRequired
    @TeacherRequired
    public Result addNewCourse(@RequestParam String courseName, @RequestParam String description, @RequestParam int maxNum,
                               @RequestParam int addType) {
        if (courseName == null || courseName.isEmpty() || courseName.length() > 50) throw new ParamInvalidException();
        if (description == null || description.isEmpty() || description.length() > 200) throw new ParamInvalidException();
        if (maxNum <= 0) throw new ParamInvalidException();
        if (addType > 1 || addType < 0) throw new ParamInvalidException();

        User teacher = authService.threadLocalUsers.get();
        Course course = new Course();
        course.courseName = courseName;
        course.description = description;
        course.maxNum = maxNum;
        course.teacherID = teacher.id;
        course.addType = addType;
        course.createdTime = System.currentTimeMillis();

        boolean success = courseService.insert(course);
        if (!success) {
            return ResultUtil.error("新增课程失败，请稍后再试");
        }
        return ResultUtil.success();
    }


    @LoginRequired
    @TeacherRequired
    @GetMapping("/application")
    public Result getApplications(@RequestParam int page, @RequestParam int limit) {
        User teacher = authService.threadLocalUsers.get();
        String sql = "SELECT\n" +
                "\tusername_course.*,\n" +
                "\tcourse.course_name \n" +
                "FROM\n" +
                "\t(\n" +
                "\tSELECT\n" +
                "\t\tuser_course.*,\n" +
                "\t\t`user`.username \n" +
                "\tFROM\n" +
                "\t\t( SELECT user_id, course_id, `status` FROM student_course_application WHERE course_id IN ( SELECT id FROM course WHERE teacher_id = ? ) AND `status` = 0 ) AS user_course\n" +
                "\t\tJOIN `user` ON `user`.id = user_course.user_id \n" +
                "\t) AS username_course\n" +
                "\tJOIN course ON course.id = username_course.course_id";

        List<HashMap<String, Object>> data = jdbcTemplate.query(sql, new RowMapper<HashMap<String, Object>>() {
            @Override
            public HashMap<String, Object> mapRow(ResultSet resultSet, int i) throws SQLException {
                HashMap<String, Object> data = new HashMap<>();
                data.put("user_id", resultSet.getInt("user_id"));
                data.put("course_id", resultSet.getInt("course_id"));
                data.put("status", resultSet.getInt("status"));
                data.put("username", resultSet.getString("username"));
                data.put("course_name", resultSet.getString("course_name"));
                return data;
            }
        }, teacher.id);

        return ResultUtil.success(data);
    }


    @LoginRequired
    @TeacherRequired
    @PostMapping("/application")
    public Result updateApplication(@RequestParam int user_id, @RequestParam int course_id, @RequestParam int status) {
        Course course = courseService.getCourseByID(course_id);
        if (course == null) throw new ParamInvalidException();

        User teacher = authService.threadLocalUsers.get();
        if (course.teacherID != teacher.id) throw new PermissionException();

        StudentCourseApplication application = studentCourseApplicationService.getByUserIDAndCourseID(user_id, course_id);
        if (application == null) throw new ParamInvalidException();

        application.status = status;
        studentCourseApplicationService.updateStatus(application);

        if (status == 1)  {
            StudentCourse studentCourse = new StudentCourse();
            studentCourse.userID = user_id;
            studentCourse.courseID = course_id;
            studentCourseService.insert(studentCourse);
        }

        return ResultUtil.success();
    }

}
